﻿#include "widget.h"
#include "ui_widget.h"
#include "transform.cpp"
#include <QFileDialog>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    WebView(new QWebEngineView),
    WebChannel(new QWebChannel),
    ChObj(new JWebChannel),
    BtnReadFile(new QPushButton(QString::fromLocal8Bit("读取数据文件"))),
    BtnWebRefresh(new QPushButton(QString::fromLocal8Bit("刷新"))),
    LabFilterType(new QLabel(QString::fromLocal8Bit("滤波器类型:"))),
    cBoxFilterType(new QComboBox),
    hLayoutFilter(new QHBoxLayout),
    LabWinType(new QLabel(QString::fromLocal8Bit("窗口类型:"))),
    cBoxWinType(new QComboBox),
    hLayoutWin(new QHBoxLayout),
    LabScala(new QLabel(QString::fromLocal8Bit("阶数:"))),
    EditScala(new QLineEdit),
    hLayoutScala(new QHBoxLayout),
    LabFreq(new QLabel(QString::fromLocal8Bit("采样频率:"))),
    EditFreq(new QLineEdit),
    hLayoutFreq(new QHBoxLayout),
    LabUpperFreq(new QLabel(QString::fromLocal8Bit("频率上限:"))),
    EditUpperFreq(new QLineEdit),
    hLayoutUpperFreq(new QHBoxLayout),
    LabLowerFreq(new QLabel(QString::fromLocal8Bit("频率下限:"))),
    EditLowerFreq(new QLineEdit),
    hLayoutLowerFreq(new QHBoxLayout),
    BtnCalcWave(new QPushButton(QString::fromLocal8Bit("计算"))),
    vLayoutWave(new QVBoxLayout),
    vLayoutSignal(new QVBoxLayout),
    vLayoutOp(new QVBoxLayout),
    hLayoutMain(new QHBoxLayout)
{
    vLayoutOp->addWidget(BtnReadFile);
    hLayoutFilter->addWidget(LabFilterType);
    hLayoutFilter->addWidget(cBoxFilterType);
    vLayoutOp->addLayout(hLayoutFilter);
    hLayoutWin->addWidget(LabWinType);
    hLayoutWin->addWidget(cBoxWinType);
    vLayoutOp->addLayout(hLayoutWin);
    hLayoutScala->addWidget(LabScala);
    hLayoutScala->addWidget(EditScala);
    vLayoutOp->addLayout(hLayoutScala);
    hLayoutFreq->addWidget(LabFreq);
    hLayoutFreq->addWidget(EditFreq);
    vLayoutOp->addLayout(hLayoutFreq);
    hLayoutUpperFreq->addWidget(LabUpperFreq);
    hLayoutUpperFreq->addWidget(EditUpperFreq);
    vLayoutOp->addLayout(hLayoutUpperFreq);
    hLayoutLowerFreq->addWidget(LabLowerFreq);
    hLayoutLowerFreq->addWidget(EditLowerFreq);
    vLayoutOp->addLayout(hLayoutLowerFreq);
    vLayoutOp->addWidget(BtnCalcWave);
    vLayoutOp->addWidget(BtnWebRefresh);
    vLayoutOp->addStretch();
    hLayoutMain->addWidget(WebView);
    hLayoutMain->addLayout(vLayoutOp);
    LabFilterType->setAlignment(Qt::AlignRight);
    LabWinType->setAlignment(Qt::AlignRight);
    LabScala->setAlignment(Qt::AlignRight);
    LabFreq->setAlignment(Qt::AlignRight);
    LabUpperFreq->setAlignment(Qt::AlignRight);
    LabLowerFreq->setAlignment(Qt::AlignRight);
    hLayoutMain->setStretch(0, 90);
    hLayoutMain->setStretch(1, 10);
    setLayout(hLayoutMain);
    showMaximized();
    // 参数设置
    cBoxFilterType->addItem(QString::fromLocal8Bit("低通"));
    cBoxFilterType->addItem(QString::fromLocal8Bit("高通"));
    cBoxFilterType->addItem(QString::fromLocal8Bit("带通"));
    cBoxFilterType->addItem(QString::fromLocal8Bit("带阻"));
    cBoxWinType->addItem(QString::fromLocal8Bit("矩形"));
    cBoxWinType->addItem(QString::fromLocal8Bit("图基"));
    cBoxWinType->addItem(QString::fromLocal8Bit("三角"));
    cBoxWinType->addItem(QString::fromLocal8Bit("汉宁"));
    cBoxWinType->addItem(QString::fromLocal8Bit("海明"));
    cBoxWinType->addItem(QString::fromLocal8Bit("布拉克曼"));
    cBoxWinType->addItem(QString::fromLocal8Bit("凯塞"));
    FilterType = Filter::LOWPASS;
    WinType = Filter::RECTANGLE;
    Scala = 64;
    EditScala->setText(QString::number(Scala));
    Freq = 1000;
    EditFreq->setText(QString::number(Freq));
    LowerFreq = 100;
    EditLowerFreq->setText(QString::number(LowerFreq));
    UpperFreq = 300;
    EditUpperFreq->setText(QString::number(UpperFreq));
    // 属性、功能设置
    connect(BtnReadFile, &QPushButton::clicked, this, &Widget::BtnReadFile_clicked);
    connect(BtnCalcWave, &QPushButton::clicked, this, &Widget::BtnCalc_clicked);
    connect(cBoxFilterType, SIGNAL(currentIndexChanged(int)), this, SLOT(cBoxFilterType_curIndexChanged(int)));
    connect(cBoxWinType, SIGNAL(currentIndexChanged(int)), this, SLOT(cBoxWinType_curIndexChanged(int)));
    connect(EditScala, &QLineEdit::editingFinished, this, &Widget::EditScala_editingFinished);
    connect(EditFreq, &QLineEdit::editingFinished, this, &Widget::EditFreq_editingFinished);
    connect(EditLowerFreq, &QLineEdit::editingFinished, this, &Widget::EditLowerFreq_editingFinished);
    connect(EditUpperFreq, &QLineEdit::editingFinished, this, &Widget::EditUpperFreq_editingFinished);
    connect(BtnWebRefresh, &QPushButton::clicked, this, &Widget::BtnWebRefresh_refreshWebView);
    // Web属性设置
    WebChannel->registerObject("context", ChObj);
    WebView->page()->setWebChannel(WebChannel);
    connect(ChObj, &JWebChannel::RecvMsg, this, &Widget::RecvJSMeg);
    WebView->load(QUrl("qrc:/file/index.html"));
    // 发送消息给js
//    ChObj->SendMsg(WebView->page(), "hello js");
}

Widget::~Widget()
{
    ChObj->deleteLater();
    WebChannel->deleteLater();
    WebView->deleteLater();
    BtnReadFile->deleteLater();
    BtnWebRefresh->deleteLater();
    LabFilterType->deleteLater();
    cBoxFilterType->deleteLater();
    hLayoutFilter->deleteLater();
    LabWinType->deleteLater();
    cBoxWinType->deleteLater();
    hLayoutWin->deleteLater();
    LabScala->deleteLater();
    EditScala->deleteLater();
    hLayoutScala->deleteLater();
    LabFreq->deleteLater();
    EditFreq->deleteLater();
    hLayoutFreq->deleteLater();
    LabUpperFreq->deleteLater();
    EditUpperFreq->deleteLater();
    hLayoutUpperFreq->deleteLater();
    LabLowerFreq->deleteLater();
    EditLowerFreq->deleteLater();
    hLayoutLowerFreq->deleteLater();
    BtnCalcWave->deleteLater();
    vLayoutWave->deleteLater();
    vLayoutSignal->deleteLater();
    vLayoutOp->deleteLater();
    hLayoutMain->deleteLater();
    delete ui;
}

void Widget::RecvJSMeg(const QString &msg)
{
    qDebug() << "Widget-->" + msg;
}

void Widget::BtnReadFile_clicked()
{
    QString file = QFileDialog::getOpenFileName(this);
    if(file.isEmpty())
        return;
    SampData.ReadDataFile(file);
    qDebug() << "Type:" << SampData.Header.bfType <<
                "bfSize:" << SampData.Header.bfSize <<
                "diVer:" << SampData.Header.diVer <<
                "diADBit:" << SampData.Header.diADBit <<
                "diSize:" << SampData.Header.diSize <<
                "diSampleFreq:" << SampData.Header.diSampleFreq <<
                "diChannelNum:" << SampData.Header.diChannelNum <<
                "diCh:" << SampData.Header.diCh <<
                "diTestPointNum:" << SampData.Header.diTestPointNum <<
                "diSensitivity:" << SampData.Header.diSensitivity <<
                "diMultiple:" << SampData.Header.diMultiple <<
                "diUnit:" << SampData.Header.diUnit <<
                "diRemark:" << SampData.Header.diRemark <<
                "diDataFlag:" << SampData.Header.diDataFlag;
    int Len = 1;
    while(Len < SampData.Header.diSize)
        Len *= 2;
    Len /= 2;
    valarray<complex<long double>> pp(static_cast<size_t>(Len));
    valarray<complex<long double>> f(static_cast<size_t>(Len));
    QJsonObject dObj;
    QJsonArray xAxis, yData;
    for (auto i = 0; i < SampData.Header.diSize; i++) {
        xAxis.append(i);
        yData.append(static_cast<double>(SampData.Data[i]));
        if(i < Len)
            pp[static_cast<size_t>(i)] = complex<long double>(static_cast<long double>(SampData.Data[i]), static_cast<long double>(0.0));
    }
    dObj.insert("type", "input");
    dObj.insert("xAxis", xAxis);
    dObj.insert("data", yData);
    QJsonDocument doc(dObj);
    ChObj->SendMsg(WebView->page(), doc.toJson(QJsonDocument::Compact));
//    ChObj->setProperty("jsonData",dObj);
    // 输入信号频谱
    FourierTransform(pp, f, 0, 1);
    QJsonObject dFFTObj;
    QJsonArray xFFTAxis, yFFTData;
    for (auto i = 0; i < Len / 2 + 1; i++) {
        xFFTAxis.append(i / ((Len / 2 + 1) / (Freq / 2)));
        yFFTData.append(static_cast<double>(pp[static_cast<size_t>(i)].real() / (Len / 2 + 1) * 2));
    }
    dFFTObj.insert("type", "inputFFT");
    dFFTObj.insert("xAxis", xFFTAxis);
    dFFTObj.insert("data", yFFTData);
    doc.setObject(dFFTObj);
    ChObj->SendMsg(WebView->page(), doc.toJson(QJsonDocument::Compact));
//    ChObj->setProperty("jsonData",dFFTObj);
}

void Widget::BtnCalc_clicked()
{
#if 1
    // 冲击响应
    if(SampData.Data == nullptr)
        return;
    Filter filter(FilterType, WinType, Scala, Freq, LowerFreq, UpperFreq);
    QVector<double> xImpuls(Scala), yImpuls(Scala);
    QJsonObject dObj;
    QJsonArray xAxis, yData;
    for (auto i = 0; i < Scala; i++) {
        xAxis.append(i);
        yData.append(filter.ImpactData[i]);
        yImpuls[i] = filter.ImpactData[i];
    }
    dObj.insert("type", "impulse");
    dObj.insert("xAxis", xAxis);
    dObj.insert("data", yData);
    QJsonDocument doc(dObj);
    ChObj->SendMsg(WebView->page(), doc.toJson(QJsonDocument::Compact));
    // 输出波形
    dObj.remove("type");
    dObj.remove("xAxis");
    dObj.remove("data");
    QJsonArray xOut, yOut;
    filter.Convolution(SampData.Data, SampData.Header.diSize);
    if(filter.OutData == nullptr)
        return;
    int Len = 1;
    while(Len < SampData.Header.diSize)
        Len *= 2;
    Len /= 2;
    valarray<complex<long double>> pp(static_cast<size_t>(Len));
    valarray<complex<long double>> f(static_cast<size_t>(Len));
    for (auto i = 0; i < SampData.Header.diSize; i++) {
        xOut.append(i);
        yOut.append(filter.OutData[i]);
        if(i < Len)
            pp[static_cast<size_t>(i)] = complex<long double>(static_cast<long double>(filter.OutData[i]), static_cast<long double>(0.0));
    }
    dObj.insert("type", "output");
    dObj.insert("xAxis", xOut);
    dObj.insert("data", yOut);
    doc.setObject(dObj);
    ChObj->SendMsg(WebView->page(), doc.toJson(QJsonDocument::Compact));
    // 输出波形的频谱
    dObj.remove("type");
    dObj.remove("xAxis");
    dObj.remove("data");
    QJsonArray xOutFFT, yOutFFT;
    FourierTransform(pp, f, 0, 1);
    QVector<double> xFreq(Len / 2 + 1), yFreqS(Len / 2 + 1);
    for (auto i = 0; i < Len / 2 + 1; i++) {
        xOutFFT.append(i / ((Len / 2 + 1) / (Freq / 2)));
        yOutFFT.append(static_cast<double>(pp[static_cast<size_t>(i)].real() / (Len / 2 + 1) * 2));
    }
    dObj.insert("type", "outputFFT");
    dObj.insert("xAxis", xOutFFT);
    dObj.insert("data", yOutFFT);
    doc.setObject(dObj);
    ChObj->SendMsg(WebView->page(), doc.toJson(QJsonDocument::Compact));
    // 频率响应
    dObj.remove("type");
    dObj.remove("xAxis");
    dObj.remove("data");
    QJsonArray xPulsFFT, yPulsFFT;
    valarray<complex<long double>> Impulspp(static_cast<size_t>(Len));
    valarray<complex<long double>> Impulsf(static_cast<size_t>(Len));
    for (auto i = 0; i < Len; i++) {
        if(i < Scala)
            Impulspp[static_cast<size_t>(i)] = complex<long double>(static_cast<long double>(yImpuls[i]), static_cast<long double>(0.0));
        else
            Impulspp[static_cast<size_t>(i)] = complex<long double>(static_cast<long double>(0.0), static_cast<long double>(0.0));
    }
    FourierTransform(Impulspp, Impulsf, 0, 1);
    QVector<double> xF(Len / 2 + 1), yF(Len / 2 + 1);
    for (auto i = 0; i < Len / 2 + 1; i++) {
        xPulsFFT.append(i / ((Len / 2 + 1) / (Freq / 2)));
        yPulsFFT.append(20.0 * log(fabs(static_cast<double>(Impulspp[static_cast<size_t>(i)].real()))));
    }
    dObj.insert("type", "impulseFFT");
    dObj.insert("xAxis", xPulsFFT);
    dObj.insert("data", yPulsFFT);
    doc.setObject(dObj);
    ChObj->SendMsg(WebView->page(), doc.toJson(QJsonDocument::Compact));
#endif
}

void Widget::cBoxFilterType_curIndexChanged(int index)
{
    FilterType = index;
}

void Widget::cBoxWinType_curIndexChanged(int index)
{
    WinType = index;
}

void Widget::EditScala_editingFinished()
{
    Scala = EditScala->text().toInt();
}

void Widget::EditFreq_editingFinished()
{
    Freq = EditFreq->text().toDouble();
}

void Widget::EditLowerFreq_editingFinished()
{
    LowerFreq = EditLowerFreq->text().toDouble();
}

void Widget::EditUpperFreq_editingFinished()
{
    UpperFreq = EditUpperFreq->text().toDouble();
}

void Widget::BtnWebRefresh_refreshWebView()
{
    WebView->reload();
}
